Skip to content

ci(web-static): gate puppeteer navigate on a bounded server health-poll - #842

Merged
frstrtr merged 1 commit into
masterfrom
ci-steward/web-static-wait-for-port
Jul 25, 2026
Merged

ci(web-static): gate puppeteer navigate on a bounded server health-poll#842
frstrtr merged 1 commit into
masterfrom
ci-steward/web-static-wait-for-port

Conversation

@frstrtr

@frstrtr frstrtr commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Problem

The Web-static verify visual harness races the mock-server start. tests/visual/run.sh capped its readiness loop at 30x0.2s = 6s and — the real bug — never checked the loop result, falling through to capture.mjs even when the server had not bound. On a busy self-hosted runner (VM905) the server binds late, puppeteer navigates a dead port, and net::ERR_CONNECTION_REFUSED surfaces as a page/pixel assertion failure — false-redding coin-side PRs that never touch web/.

Repro: job 89644021788, run 30144644836, PR #839 (btc-only change). Same check green on #837/#840/#841 off the same base → job-level flake, not a regression.

Fix (milestone points 1-4)

  1. Wait-for-port health-poll on 127.0.0.1:$PORT before navigating — bounded 60s (READY_TIMEOUT override), replacing the 6s race.
  2. Gated + distinguishable failure: if the server never comes up, exit 3 with an ::error::INFRA (not a page regression) message + tail of mock-server.log, so an infra flake is never reported as a page assertion. Also bails early if the server pid dies (e.g. port in use).
  3. chrome-for-testing retry already gates (build.yml): test -x \$CHROME_BIN || exit 1 after 3 attempts. The blip-then-continue seen in the failing log was the retry succeeding on a transient chrome fetch; the actual failure was the downstream port race fixed here. No swallowed error — no change needed.
  4. Only job navigating a locally-started server is this one; release.yml/pplns-parse-seedpin web-static hits are packaging copies, not navigation. No other target.

Acceptance

Web-static verify runs regardless of path, so this PR triggers it; a green run will show [2b] waiting up to 60s...mock server ready after Ns, demonstrating the wait loop firing. A btc-only src/impl/btc/** PR can no longer fail this check on port/chrome availability.

The visual harness raced the mock-server start: the readiness loop was
capped at 30x0.2s=6s and, worse, never checked its own result — it fell
through to capture.mjs even when the server had not bound. On a busy
self-hosted runner (VM905) the server binds late and puppeteer navigates
into a dead port, producing net::ERR_CONNECTION_REFUSED that surfaces as
a page/pixel assertion failure and false-reds coin-side PRs that never
touch web/ (job 89644021788, run 30144644836, PR #839).

Make the wait a real gate: health-poll 127.0.0.1:PORT (bounded 60s,
override via READY_TIMEOUT), bail early if the server process dies, and
on timeout fail with a distinguishable INFRA message + server log tail
instead of letting puppeteer report an infra flake as a page regression.
@frstrtr
frstrtr merged commit 84232d8 into master Jul 25, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant